﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml.Linq;
using RenjianImageViewer.Util;
using System.Windows.Data;
using System.Windows.Media.Animation;

/*
 11/27 new feature:
 * checknew
 * save all
 * create folder
 */
namespace RenjianImageViewer.View.Window
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        private static ViewModel.RenjianViewModel viewModel = new ViewModel.RenjianViewModel();
        private Dictionary<long, FrameworkElement> imageCache = new Dictionary<long, FrameworkElement>();
        private long lastID = 0;
        private long latestID = 0;
        private bool checkNew = true;
        private bool free = true;
        private DispatcherTimer timer = new DispatcherTimer();

        private List<long> failedThumbnailList = new List<long>();

        //For Config panel
        private Binding positionBinding = null;
        private bool isConfiguring = false;

        private int viewid = 0;
        private FluidKit.Controls.LayoutBase[] layouts = new FluidKit.Controls.LayoutBase[]
            {
                new FluidKit.Controls.Wall(),
                //new FluidKit.Controls.Carousel(),
                //new FluidKit.Controls.CoverFlow(),
                //new FluidKit.Controls.RollerCoaster(),
                //new FluidKit.Controls.Rolodex(),
                //new FluidKit.Controls.SlideDeck(),
                //new FluidKit.Controls.ThreeLane(),
                //new FluidKit.Controls.TimeMachine(),
                //new FluidKit.Controls.TimeMachine2(),
                //new FluidKit.Controls.VForm(),
                //new FluidKit.Controls.Wall()
            };

        public MainWindow()
        {
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
            InitializeComponent();
            this.DataContext = viewModel;
            BigImage.DataContext = null;
            BigImage.MouseDown += new MouseButtonEventHandler(a_MouseDown);
            if (!Directory.Exists(@"c:\\rensea\"))
            {
                Directory.CreateDirectory(@"c:\\rensea\");
            }
            Button_Click(null, null);

            positionBinding = new Binding("ActualHeight");
            positionBinding.Source = ConfigContent;
            positionBinding.Converter = new TestConvert();
            ConfigPanel.SetBinding(TabControl.RenderTransformProperty, positionBinding);
        }

        void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            MessageBox.Show((e.ExceptionObject as Exception).Message);
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.Key == Key.F12)
            {
                if (viewid < layouts.Length)
                {
                    _elementFlow.Layout = layouts[viewid];
                    _elementFlow.ItemsSource = viewModel.Images;
                    RockViewGrid.Visibility = System.Windows.Visibility.Visible;
                    viewid++;
                }
                else
                {
                    RockViewGrid.Visibility = System.Windows.Visibility.Collapsed;
                    viewid = 0;
                }
                e.Handled = true;
            }
            base.OnKeyDown(e);
        }

        void a_MouseDown(object sender, MouseButtonEventArgs e)
        {
            PopupTools.IsOpen = true;
        }
        private void SaveSingleImage()
        {
            BusyMask.DataContext = new ViewModel.SavingStateViewModel { ShowState = false };
            BusyMask.Visibility = Visibility.Visible;
            ViewModel.ImageViewModel imageVM = BigImage.DataContext as ViewModel.ImageViewModel;

            if (false == imageVM.IsLocal)
            {
                WebClient wc = new WebClient();
                //Hack to remove watermark
                wc.Headers.Add(HttpRequestHeader.Referer, "http://renjian.com/home");
                wc.DownloadProgressChanged += (s, e) => (BusyMask.DataContext as ViewModel.SavingStateViewModel).Percentage = e.ProgressPercentage;
                wc.DownloadFileCompleted += (s, e) =>
                {
                    WebClient webClient = e.UserState as WebClient;
                    if (null != webClient)
                    {
                        webClient.Dispose();
                    }
                    BusyMask.Visibility = Visibility.Collapsed;
                    imageVM.IsLocal = true;
                };
                wc.DownloadFileAsync(new Uri(imageVM.ImageUrl), @"c:\\rensea\" + imageVM.StatusID.ToString() +
                        System.IO.Path.GetExtension(imageVM.ImageUrl), wc);
            }

            //Thread t = new Thread(SaveSingleImageProc);
            //t.IsBackground = true;
            //t.Start(BigImage.DataContext);
        }
        //private void SaveSingleImageProc(object viewModelObject)
        //{
        //    ViewModel.ImageViewModel imageVM = viewModelObject as ViewModel.ImageViewModel;
        //    if (false == (bool)Dispatcher.Invoke((Func<bool>)(()=>imageVM.IsLocal)))
        //    {
        //        WebClient wc = new WebClient();
        //        {
        //            wc.DownloadProgressChanged += (s, e) => Dispatcher.Invoke((Action)(() =>
        //            { Title=e.ProgressPercentage.ToString(); }), null);
        //            wc.DownloadFileCompleted += (s, e) => 
        //                {
        //                    WebClient webClient = e.UserState as WebClient;
        //                    if (null != webClient)
        //                    {
        //                        webClient.Dispose();
        //                    }
        //                    Dispatcher.Invoke((Action)(() =>
        //                    { BusyMask.Visibility = Visibility.Collapsed; imageVM.IsLocal = true; }), null);
        //                };
        //            wc.DownloadFileAsync(new Uri(imageVM.ImageUrl), @"c:\\rensea\" + imageVM.StatusID.ToString() +
        //                    System.IO.Path.GetExtension(imageVM.ImageUrl), wc);
        //        }
        //    }
        //    //Dispatcher.Invoke((Action)(() =>
        //    //{ BusyMask.Visibility = Visibility.Collapsed; imageVM.IsLocal = true; }), null);
        //}

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            WebClient wc = new WebClient();
            wc.Encoding = Encoding.UTF8;
            IEnumerable<ViewModel.ImageViewModel> images;

            string result = wc.DownloadString("http://api.renjian.com/statuses/public_timeline.xml?count=50");
            XElement xRoot = result.ParseToXElement();
            images = from status in xRoot.Elements("status")
                     where status.Element("status_type").Value == "PICTURE"
                     select new ViewModel.ImageViewModel(status.ToString())
                     {
                         StatusID = (long)status.Element("id"),
                         ImageUrl = status.Element("original_url").Value,
                         ThumbnailUrl = status.Element("thumbnail").Value
                     };
            lastID = (long)xRoot.Elements("status").Last().Element("id");
            latestID = (long)xRoot.Elements("status").First().Element("id");

            if (images.Count() > 0)
            {
                foreach (var image in images)
                {
                    viewModel.AddImage(image);
                }
            }
            if (viewModel.Images.Count < 15)
            {
                GetMore(15 - viewModel.Images.Count);
            }
            //(e.Source as Button).Visibility = System.Windows.Visibility.Collapsed;

            timer.Tick += new EventHandler(dispatcherTimer_Tick);
            timer.Interval = new TimeSpan(0, 0, 5);
            timer.Start();
        }

        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            viewModel.NewImages.Clear();
            if (checkNew)
            {
                var getNewTask = Task.Factory.StartNew(() =>
                {
                    WebClient wc = new WebClient();
                    wc.Encoding = Encoding.UTF8;
                    string result = wc.DownloadString(string.Format("http://api.renjian.com/statuses/public_timeline.xml?since_id={0}&count=500", latestID));
                    wc.Dispose();
                    return result.ParseToXElement();
                }).ContinueWith(task =>
                    {
                        var result = task.Result;
                        var images = from status in result.Elements("status")
                                     where status.Element("status_type").Value == "PICTURE"
                                     select new ViewModel.ImageViewModel(status.ToString())
                                     {
                                         StatusID = (long)status.Element("id"),
                                         ImageUrl = status.Element("original_url").Value,
                                         ThumbnailUrl = status.Element("thumbnail").Value
                                     };
                        Dispatcher.Invoke((Action)(() =>
                            {
                                foreach (var image in images)
                                {
                                    viewModel.NewImages.Add(image);
                                    viewModel.Images.Insert(0, image);
                                }
                            }), null);
                        if (result.HasElements)
                        {
                            latestID = (long)result.Elements("status").First().Element("id");
                        }
                    }, TaskContinuationOptions.OnlyOnRanToCompletion);/*
                Task.Factory.FromAsync(getNewTask, state =>
                    {
                        var result = (state as Task<XElement>).Result;
                        var images = from status in result.Elements("status")
                                     where status.Element("status_type").Value == "PICTURE"
                                     select new ViewModel.ImageViewModel(status.ToString())
                                     {
                                         StatusID = (long)status.Element("id"),
                                         ImageUrl = status.Element("original_url").Value,
                                         ThumbnailUrl = status.Element("thumbnail").Value
                                     };
                        Dispatcher.Invoke((Action)(() =>
                            {
                                foreach (var image in images)
                                {
                                    viewModel.NewImages.Add(image);
                                    viewModel.Images.Insert(0, image);
                                }
                            }), null);
                        if (result.HasElements)
                        {
                            latestID = (long)result.Elements("status").First().Element("id");
                        }
                    });*/
            }
            checkNew = !checkNew;
        }

        private void imageList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count <= 0)
            {
                return;
            }
            if (imageList.SelectedIndex == imageList.Items.Count - 1)
            {
                GetMore();

                ScrollViewer sv = FindScroll(imageList);
                sv.ScrollToHorizontalOffset(sv.ScrollableWidth);
            }

            BigImage.DataContext = null;
            BigImage.Content = null;
            ViewModel.ImageViewModel item = e.AddedItems[0] as ViewModel.ImageViewModel;
            viewModel.CurrentImage = item;
            BigImage.DataContext = item;

            if (imageCache.ContainsKey(item.StatusID))
            {
                BigImage.Content = imageCache[item.StatusID];
                if (progressBarLoading.Visibility != System.Windows.Visibility.Collapsed)
                {
                    progressBarLoading.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
            else
            {
                item.DownloadStreamCompleted += DownloadBigImageCompleteCallBack;
                progressBarLoading.DataContext = item;
                progressBarLoading.Visibility = System.Windows.Visibility.Visible;
                item.DownloadStreamAsync();
            }

            if (e.Source != conversitionImageList &&
                (null == viewModel.ConversitionImages || null == viewModel.ConversitionImages.FirstOrDefault(imgVM => imgVM.StatusID == item.StatusID)))
            {
                viewModel.ConversitionImages.Clear();
                Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            WebClient wc = new WebClient();
                            wc.Credentials = new NetworkCredential(
                                "dummy",
                                "123456");
                            wc.Encoding = Encoding.UTF8;
                            string result = wc.DownloadString(string.Format("http://api.renjian.com/conversations/show_by_status/{0}.xml?show_all=true", item.StatusID.ToString()));
                            wc.Dispose();
                            XElement xRoot = result.ParseToXElement();
                            var images = from status in xRoot.Elements("status")
                                         where status.Element("status_type").Value == "PICTURE"
                                         select status;
                            this.Dispatcher.Invoke((Action)(() =>
                                {
                                    if (viewModel.ConversitionImages.Count == 0 &&
                                        item.StatusID == viewModel.CurrentImage.StatusID)
                                    {
                                        foreach (var image in images)
                                        {
                                            viewModel.ConversitionImages.Add(
                                                new ViewModel.ImageViewModel(image.ToString())
                                                     {
                                                         StatusID = (long)image.Element("id"),
                                                         ImageUrl = image.Element("original_url").Value,
                                                         ThumbnailUrl = image.Element("thumbnail").Value
                                                     });
                                        }
                                    }
                                }), DispatcherPriority.Send, null);
                        }
                        catch { }
                    });
            }
        }

        private void DownloadBigImageCompleteCallBack(object sender, EventArgs e)
        {
            ViewModel.ImageViewModel imageVM = sender as ViewModel.ImageViewModel;
            if (!imageCache.ContainsKey(imageVM.StatusID))
            {
                imageCache.Add(imageVM.StatusID, imageVM.Image);
            }
            if (imageVM.StatusID == viewModel.CurrentImage.StatusID)
            {
                BigImage.Content = imageCache[imageVM.StatusID];
                progressBarLoading.Visibility = System.Windows.Visibility.Collapsed;
            }
            imageVM.DownloadStreamCompleted -= DownloadBigImageCompleteCallBack;
        }

        private void imageList_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            ScrollViewer sv = FindScroll(imageList);

            if (e.Delta > 0)
            {
                sv.ScrollToHorizontalOffset(sv.HorizontalOffset - 50);
            }
            else
            {
                sv.ScrollToHorizontalOffset(sv.HorizontalOffset + 50);
                if (sv.HorizontalOffset >= sv.ScrollableWidth)
                {
                    GetMore();
                }
            }
        }

        private void GetMore()
        {
            GetMore(5);
        }
        private void GetMore(int max)
        {
            if (free)
            {
                free = false;
                viewModel.IsBusy = true;
                Thread t = new Thread(GetMoreProc);
                t.IsBackground = true;
                t.Start(max);
            }
        }

        private XElement taskproc(object i)
        {
            long id = (long)i;
            try
            {
                if (id <= 1)
                {
                    return null;
                }

                using (WebClient wc = new WebClient())
                {
                    wc.Encoding = Encoding.UTF8;
                    string result = 
                        wc.DownloadString(string.Format("http://api.renjian.com/statuses/show/{0}.xml", id));

                    XElement xStatus = result.ParseToXElement();
                    if (xStatus.Element("status_type").Value == "PICTURE")
                    {
                        if (null != xStatus.Element("original_url") && null != xStatus.Element("thumbnail"))
                        {
                            return xStatus;
                        }
                    }
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        private List<XElement> getImageJob(object tryRangeObj)
        {
            //int tryRange = (int)tryRangeObj;
            //var result = ImageFetcher.GetMoreImages((int)lastID, tryRange);
            //lastID -= tryRange;
            //return result.ToList();
            int tryRange = (int)tryRangeObj;
            Task<XElement>[] taskGroup = new Task<XElement>[tryRange];
            for (long taskId = lastID - tryRange, index = tryRange - 1; taskId < lastID; taskId++, index--)
            {
                taskGroup[index] =
                    Task.Factory.StartNew<XElement>(taskproc, taskId);
            }
            lastID -= tryRange;

            //Blog how to fix the block UI issue.
            return (from task in taskGroup where task.Result != null select task.Result).ToList();
        }

        private void addImageJob(object imageStatusList)
        {
            dynamic imageStatus = imageStatusList;
            this.Dispatcher.Invoke((Action)(() =>
            {
                foreach (var img in imageStatus)
                {
                    viewModel.AddImage(
                    new ViewModel.ImageViewModel(img.ToString())
                    {
                        StatusID = (long)img.Element("id"),
                        ImageUrl = img.Element("original_url").Value,
                        ThumbnailUrl = img.Element("thumbnail").Value
                    });
                }
            }), null);
            GC.Collect();
        }

        private void GetMoreProc(object max)
        {
            int maxNumber = (int)max;
            int count = 0;
            bool move = true;

            int tryRange = 50;
            int continueEmptyTimes = 0;

            //tryRange tune
            Task<List<XElement>> getImageTask = Task.Factory.StartNew<List<XElement>>(getImageJob, tryRange);
            while (move)
            {
                var imgList = getImageTask.Result;
                count += imgList.Count;
                if (count < maxNumber)
                {
                    getImageTask = Task.Factory.StartNew<List<XElement>>(getImageJob, tryRange);
                }
                else
                {
                    move = false;
                }

                if (imgList.Count != 0)
                {
                    addImageJob(imgList);
                    continueEmptyTimes = 0;
                }
                else if (++continueEmptyTimes >= 2)
                {
                    tryRange = tryRange * 2;
                }
            }



            //int maxNumber = (int)max;
            //int count = 0;
            //SortedList<long, string> cacheList = new SortedList<long, string>();
            //do
            //{
            //    Parallel.For(lastID - 49, lastID, (id) =>
            //    {
            //        try
            //        {
            //            if (id <= 1)
            //            {
            //                return;
            //            }

            //            WebClient wc = new WebClient();
            //            wc.Encoding = Encoding.UTF8;
            //            string result = wc.DownloadString(string.Format("http://api.renjian.com/statuses/show/{0}.xml", id));
            //            wc.Dispose();

            //            XElement xStatus = result.ParseToXElement();
            //            if (xStatus.Element("status_type").Value == "PICTURE")
            //            {
            //                if (null != xStatus.Element("original_url") && null != xStatus.Element("thumbnail"))
            //                {
            //                    lock (cacheList)
            //                    {
            //                        cacheList.Add(-1 * (long)xStatus.Element("id"), result);
            //                        Interlocked.Increment(ref count);
            //                    }
            //                }

            //            }
            //        }
            //        catch { }
            //    });
            //    this.Dispatcher.Invoke((Action)(() =>
            //    {
            //        foreach (var statusStr in cacheList.Values)
            //        {
            //            var status = statusStr.ParseToXElement();
            //            viewModel.Images.Add(
            //                new ViewModel.ImageViewModel(status.ToString())

            //                {
            //                    StatusID = (long)status.Element("id"),
            //                    ImageUrl = status.Element("original_url").Value,
            //                    ThumbnailUrl = status.Element("thumbnail").Value
            //                });
            //        }
            //    }), null);
            //    cacheList.Clear();
            //    GC.Collect();
            //    lastID -= 50;

                //string val;
                //try
                //{
                //    if (lastID <= 1)
                //    {
                //        break;
                //    }
                //    string result = wc.DownloadString(string.Format("http://api.renjian.com/statuses/show/{0}.xml", --lastID));
                //    val = result;
                //    XElement xStatus = XElement.Parse(result);
                //    if (xStatus.Element("status_type").Value == "PICTURE")
                //    {
                //        if (null != xStatus.Element("original_url") && null != xStatus.Element("thumbnail"))
                //        {
                //            this.Dispatcher.Invoke((Action)(() =>
                //                viewModel.Images.Add(
                //                new ViewModel.ImageViewModel(xStatus.ToString())
                //                {
                //                    StatusID = (long)xStatus.Element("id"),
                //                    ImageUrl = xStatus.Element("original_url").Value,
                //                    ThumbnailUrl = xStatus.Element("thumbnail").Value
                //                })), null);
                //            count++;
                //        }
                //    }
                //}
                //catch (WebException)
                //{
                //    continue;
                //}
                //catch
                //{
                //    continue;
                //}
            //} while (count < maxNumber);
            free = true;
            this.Dispatcher.Invoke((Action)(() => viewModel.IsBusy = false), null);
        }

        public static ScrollViewer FindScroll(DependencyObject listBox)
        {
            Border scrollBorder = VisualTreeHelper.GetChild(listBox, 0) as Border;
            if (scrollBorder == null) return null;

            ScrollViewer scrollViewer = scrollBorder.Child as ScrollViewer;
            return scrollViewer;
        }

        private void Image_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 3)
            {
                SaveConversitionImages();
            }
        }

        private void SaveConversitionImages()
        {
            var saveState = new ViewModel.SavingMultiImageStateViewModel { ShowState = true, Count = viewModel.ConversitionImages.Count };
            BusyMask.DataContext = saveState;
            BusyMask.Visibility = Visibility.Visible;

            int closureImageCount = viewModel.ConversitionImages.Count;

            for (int i = 0; i < viewModel.ConversitionImages.Count; i++)
            {
                WebClient wc = new WebClient();
                //Hack to remove watermark
                wc.Headers.Add(HttpRequestHeader.Referer, "http://renjian.com/home");
                wc.DownloadProgressChanged += (s, e) =>
                {
                    dynamic state = e.UserState;
                    saveState.SetPerentage(state.Index, e.ProgressPercentage);
                };
                wc.DownloadFileCompleted += (s, e) =>
                {
                    saveState.Position++;
                    dynamic state = e.UserState;
                    WebClient webClient = state.DownloadWorker;
                    if (null != webClient)
                    {
                        webClient.Dispose();
                    }
                    if (saveState.Position == closureImageCount)
                    {
                        viewModel.UpdateImagesIsLocalStatus();
                        BusyMask.Visibility = Visibility.Collapsed;
                    }
                };
                wc.DownloadFileAsync(new Uri(viewModel.ConversitionImages[i].ImageUrl),
                        @"c:\\rensea\" + viewModel.ConversitionImages[i].StatusID.ToString() +
                        System.IO.Path.GetExtension(viewModel.ConversitionImages[i].ImageUrl), new { DownloadWorker = wc, Index = i });
            }

            //Thread t = new Thread(SaveConversitionImagesProc);
            //t.IsBackground = true;
            //t.Start(BusyMask.DataContext);
        }
        private void SaveConversitionImagesProc(object dataContext)
        {
            ViewModel.SavingStateViewModel savingState = dataContext as ViewModel.SavingStateViewModel;
            using (WebClient wc = new WebClient())
            {
                foreach (var img in viewModel.ConversitionImages)
                {
                    if (false == (bool)Dispatcher.Invoke((Func<bool>)(() =>
                    {
                        savingState.Position++; return img.IsLocal;
                    })))
                    {
                        wc.DownloadFile(img.ImageUrl,
                            @"c:\\rensea\" + img.StatusID.ToString() +
                            System.IO.Path.GetExtension(img.ImageUrl));
                    }
                }
            }
            Dispatcher.Invoke((Action)(() =>
            {
                viewModel.UpdateImagesIsLocalStatus();
                BusyMask.Visibility = Visibility.Collapsed;
            }), null);
        }

        private void RepeatButtonLeft_Click(object sender, RoutedEventArgs e)
        {
            ScrollViewer sv = FindScroll(imageList);
            sv.ScrollToHorizontalOffset(sv.HorizontalOffset - 80);
        }
        private void RepeatButtonRight_Click(object sender, RoutedEventArgs e)
        {
            ScrollViewer sv = FindScroll(imageList);
            sv.ScrollToHorizontalOffset(sv.HorizontalOffset + 80);
            if (sv.HorizontalOffset >= sv.ScrollableWidth)
            {
                GetMore();
            }
        }

        private void ButtonNavigateHead_Click(object sender, RoutedEventArgs e)
        {
            ScrollViewer sv = FindScroll(imageList);
            sv.ScrollToLeftEnd();
        }
        private void ButtonNavigateEnd_Click(object sender, RoutedEventArgs e)
        {
            ScrollViewer sv = FindScroll(imageList);
            sv.ScrollToRightEnd();
        }

        private void SaveAllButtonClicked(object sender, MouseButtonEventArgs e)
        {
            PopupTools.IsOpen = false;
            SaveConversitionImages();
        }
        private void SaveImageButtonClicked(object sender, MouseButtonEventArgs e)
        {
            PopupTools.IsOpen = false;
            SaveSingleImage();
        }

        private void Image_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {
            dynamic img = e.Source;

            if (!failedThumbnailList.Contains(img.DataContext.StatusID))
            {
                img.Source = img.DataContext.Thumbnail;
                failedThumbnailList.Add(img.DataContext.StatusID);
            }
        }

        private void Thumb_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
        {

        }

        private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
        {
            TranslateTransform t = ConfigPanel.RenderTransform as TranslateTransform;
            t.Y += e.VerticalChange;
        }

        private void Thumb_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
        {
            TranslateTransform trans = this.ConfigPanel.RenderTransform as TranslateTransform;

            DoubleAnimation expandAnimation = new DoubleAnimation();
            expandAnimation.Duration = TimeSpan.FromSeconds(0.1);
            expandAnimation.Completed += new EventHandler(expandAnimation_Completed);

            if (this.ActualHeight + trans.Y > 100 && isConfiguring == false ||
                trans.Y > -80 && isConfiguring == true)
            {
                expandAnimation.To = 0;
            }
            else
            {
                expandAnimation.To = -8 - ConfigContent.ActualHeight;
            }
            this.ConfigPanel.RenderTransform.BeginAnimation(TranslateTransform.YProperty, expandAnimation);
        }

        void expandAnimation_Completed(object sender, EventArgs e)
        {
            TranslateTransform trans = this.ConfigPanel.RenderTransform as TranslateTransform;
            double curY = trans.Y;
            trans.Y = curY;
            trans.BeginAnimation(TranslateTransform.YProperty, null);

            if (0 == curY)
            {
                BindingOperations.ClearBinding(ConfigPanel, TabControl.RenderTransformProperty);
                ConfigPanel.RenderTransform = new TranslateTransform(0, 0);
                ConfigMask.Visibility = System.Windows.Visibility.Visible;
                isConfiguring = true;
            }
            else
            {
                ConfigPanel.SetBinding(TabControl.RenderTransformProperty, positionBinding);
                ConfigMask.Visibility = System.Windows.Visibility.Collapsed;
                isConfiguring = false;
            }
        }
    }

    class TestConvert : IValueConverter
    {
        TranslateTransform trans = new TranslateTransform();

        object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double v = (double)value;
            trans.Y = -8 - v;
            return trans;
        }

        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double v = (double)value;
            trans.Y = -8 - v;
            return trans;
        }
    }
}